/*
 * @Author: your name
 * @Date: 2022-02-16 10:46:51
 * @LastEditTime: 2022-03-03 15:28:16
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \vue3template\src\utils\tree.ts
 */

/**
 * 获取树的第一个子节点
 * @param treeData 
 * @returns 
 */
export const getFirstNodeByTree = (treeData) => {
  let node = null
  for (let i = 0; i < treeData.length; i++) {
    const element = treeData[i]
    if (element.children && element.children.length > 0) {
      node = getFirstNodeByTree(element.children)
    } else {
      node = element
    }
    if (node) {
      break
    }
  }
  return node
}

/**
 * 查找一个符合条件的节点
 * @param treeData 树结构数据
 * @param condition 查找条件
 * @returns 
 */
export const findTreeNode = (treeData, condition) => {
  let node = null

  for (let i = 0; i < treeData.length; i++) {
    const element = treeData[i]
    if (condition(element)) {
      node = element
    } else if (element.children && element.children.length > 0) {
      node = findTreeNode(element.children, condition)
    }
    if (node) {
      break
    }
  }

  return node
}

/**
 * 查找所有符合条件的节点
 * @param treeData 树结构数据
 * @param condition 查找条件
 * @returns 
 */
export const filterTreeNode = (treeData, condition) => {
  let nodes = []

  for (let i = 0; i < treeData.length; i++) {
    const element = treeData[i]
    if (condition(element)) {
      nodes.push(element)
    }
    if (element.children && element.children.length > 0) {
      nodes = nodes.concat(filterTreeNode(element.children, condition))
    }
  }

  return nodes
}


/**
 * 递归遍历整棵树结构，在回调中传回每个树节点
 * @param treeData 树结构数据
 * @param callback 回调，入参：树的每个节点
 */
export const foreachTreeData = (treeData, callback, parent = null) => {
  treeData.forEach(node => {
    callback(node, parent)
    if (node.children && node.children.length) {
      foreachTreeData(node.children, callback, node)
    }
  })
}

/**
 * 递归遍历整棵树结构，在回调中传回每个树节点，可控制停止遍历
 * @param treeData 树结构数据
 * @param callback 回调，入参：树的每个节点
 */
export const foreachTreeDataCtrl = (treeData, callback, parent = null) => {
  for (let i = 0; i < treeData.length; i++) {
    const node = treeData[i];
    const flag = callback(node, parent)
    if (flag === false) {
      return
    }
    if (node.children && node.children.length) {
      foreachTreeDataCtrl(node.children, callback, node)
    }
  }
}

/**
 * 获取el-tree组件中的tree data 的展开/收起状态节点
 * @param {*} treeData el-tree组件的树数据（node对象，非data）
 * @param {*} nodeKey el-tree组件的node-key
 */
export const getExpandedNodeKeys = (treeData = [], nodeKey = 'id', defaultValue = [], isExpanded = true) => {
  let expandedIds = []
  const nodesMap = treeData
  if (nodesMap) {
    for (let key in nodesMap) {
      const obj = nodesMap[key]
      if (!obj) {
        continue
      }
      if (isExpanded) {
        if (obj.expanded) {
          expandedIds.push(obj.data[nodeKey])
        }
      } else {
        if (!obj.expanded) {
          expandedIds.push(obj.data[nodeKey])
        }
      }
    }
  }
  if (!expandedIds.length) {
    expandedIds = defaultValue
  }
  return expandedIds
}

/**
 * 过滤树节点，返回结构树
 * @param {Array} treeData 树结构
 * @param {Function} condition 筛选条件，传入参数node
 */
export const filterTreeData = (_treeData = [], condition) => {
  if (!condition) {
    return
  }
  let treeData = JSON.parse(JSON.stringify(_treeData))
  treeData = treeData.filter(ele => condition(ele, null))
  foreachTreeData(treeData, (node) => {
    if (node.children && node.children.length) {
      const children = node.children.filter(ele => condition(ele, node))
      if (children && children.length) {
        node.children = children
      } else {
        delete node.children
      }
    }
  })
  return treeData
}

/**
 * 扁平化结构树
 * @param {Array} treeData 树结构
 */
export const flattenTreeData = (_treeData = []) => {
  let result = []
  foreachTreeData(_treeData,(node)=>{
    result.push(node)
  })
  return result
}

/**
 * 计算某节点下有多少个子/孙节点
 * @param {Array} treeData 树结构
 */
export const getTotalOfChild = (tree, leafOnly = false) => {
  let result = [];
  foreachTreeData(tree.children || [], (node) => {
    if (leafOnly) {
      if (!node.children?.length) {
        result.push(node);
      }
    } else {
      result.push(node);
    }
  });
  return result.length;
};

/**
 * 计算树节点有多少层
 * @param {*} tree 
 * @returns 
 */
export const getTreeMaxLevel = (tree) => {
  if (Array.isArray(tree)) {
    // 如果传入的参数是数组类型，则表示为树节点
    let maxDepth = -1; // 初始化最大深度为-1

    for (let i = 0; i < tree.length; i++) {
      const depth = getTreeMaxLevel(tree[i].children); // 对每个子节点进行递归调用

      if (depth > maxDepth) {
        maxDepth = depth; // 更新最大深度值
      }
    }

    return maxDepth + 1; // 返回当前节点所在的层数加上根节点本身
  } else {
    return 0; // 非数组类型的节点视为根节点，直接返回0作为第一层
  }
};
